/**
 * 
 */
package it.polimi.cg16.net;

import it.polimi.cg16.controller.Game;
import it.polimi.cg16.controller.PlayerController;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * @author Michele
 * 
 */
public class GameDatabase {
    /**
     * The database that contains the couple player and associated game
     */
    private Map<String, PlayerController> database = new HashMap<>();
    /**
     * The list of the waiting player
     */
    private List<PlayerController> waitPlayerList = new ArrayList<>();

    /**
     * This method check if there is a player with the given name in the
     * database
     * 
     * @param username
     * @return true if there is, false otherwise
     */
    public boolean hasPlayer(String username) {
        return database.containsKey(username);
    }

    /**
     * This method verifies if the player with the given username is active and
     * present, to prevent duplication of key
     * 
     * @param username
     *            insert by the player
     * @return true if the player is active, false otherwise
     */
    public boolean isActive(String username) {
        if (hasPlayer(username)) {
            return database.get(username).isActive();
        }
        return isInWaitList(username);
    }

    /**
     * Add a list of playerController to update the hashMap database
     * 
     * @param players
     * @param game
     */
    public synchronized void updateDatabase() {
        for (PlayerController player : waitPlayerList) {
            database.put(player.getUsername(), player);
        }
        resetWaitPlayers();
    }

    /**
     * Remove all the players of the given game from the database
     * 
     * @param game
     */
    public void removePlayers(Game game) {
        Set<Entry<String, PlayerController>> set = database.entrySet();
        Iterator<Entry<String, PlayerController>> i = set.iterator();
        while (i.hasNext()) {
            Map.Entry<String, PlayerController> entry = (Map.Entry<String, PlayerController>) i.next();
            if (game.equals(entry.getValue().getGame())) {
                i.remove();
            }
        }
    }

    /**
     * Get the playerController that already exists with the given name
     * 
     * @param player
     */
    public PlayerController getPlayer(String username) {
        return database.get(username);
    }

    /**
     * Remove the player from the wait list if present
     * 
     * @param username
     *            of the player to be removed
     */
    public void removeFromWaitList(String username) {
        for (PlayerController player : waitPlayerList) {
            if (username.equals(player.getUsername())) {
                waitPlayerList.remove(player);
            }
        }
    }

    /**
     * Add a player to the waiting player list
     * 
     * @param player
     */
    public synchronized void addPlayer(PlayerController player) {
        waitPlayerList.add(player);
    }

    /**
     * 
     * @return the size of the waiting player list
     */
    public synchronized int waitPlayerSize() {

        return waitPlayerList.size();
    }

    /**
     * 
     * @return the list of the waiting players
     */
    public List<PlayerController> getWaitPlayers() {
        return waitPlayerList;
    }

    /**
     * Clear the waiting player list
     */
    private void resetWaitPlayers() {
        waitPlayerList.clear();
    }

    /**
     * This method verifies if a player with the given username is in the wait
     * list
     * 
     * @param username
     * @return true if the player is found it, false otherwise
     */
    private boolean isInWaitList(String username) {
        for (PlayerController player : waitPlayerList) {
            if (username.equals(player.getUsername())) {
                return true;
            }
        }
        return false;
    }

}
